package parasoft.centrap.utils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

public class ClassUtil {
	/**
	 * Por�wnuje dwa obiekty na podstawie ich klas
	 * @param o1
	 * @param o2
	 * @return boolean
	 * @since centrala-2_44
	 */
	public static boolean equalsClass(final Object o1, final Object o2){
		if((o1==null) || (o2==null)){
			return false;
		}
		return o1.getClass().isInstance(o2)||o2.getClass().isInstance(o1);
	}
	/**
	 * @param <T>
	 * @param o
	 * @return
	 * @since centrala-2_44
	 */
	@SuppressWarnings("unchecked")
	public static <T>T toValue(final Object o){
		try{
			return (T)o;
		}catch(final Exception e){return null;}
	}
	/**
	 * W pe�ni bezpieczna metoda.
	 * Klasa jest pobierana z przekazywanego obiektu
	 * @param <T>
	 * @param o
	 * @return Class
	 * @since centrala-2_44
	 */
	public static <T>Class<T> getClass(final Object o){
		if(o==null){
			return null;
		}
		return toValue(o.getClass());
	}
	/**
	 * Pobiera parametry ze sparametryzowanego obiektu
	 * @param o in
	 * @return Type czyli czym jest E,T,V,K itd.
	 * @since centrala-2_44
	 */
	public static Type getParameterizedType(final Object o){
		return getParameterizedTypes(o)[0];
	} 
	/**
	 * Pobiera parametr ze sparametryzowanego obiektu
	 * @param o in
	 * @return
	 * @since centrala-2_44
	 */
	public static Type[] getParameterizedTypes(final Object o){
		if(o!=null){
			final Class<?> co = o.getClass();
			final Type type = co.getGenericSuperclass();
			if(type instanceof ParameterizedType){
				return ((ParameterizedType)type).getActualTypeArguments();
			}
		}
		return new Type[]{null};
	}  
	/**
	 * Pobiera liste z hierarchi� klas obiektu obj
	 * @param <T>
	 * @param obj
	 * @return
	 */
	public static <T>List<Class<T>> getClasses(final T obj){
		final List<Class<T>> out = new ArrayList<Class<T>>();
		if(obj!=null){
			Class<T> cclass = null;
			if(obj instanceof Class<?>){
				cclass = ClassUtil.toValue(((Class<?>)obj));
			}else{
				cclass = ClassUtil.toValue(obj.getClass());
			}
			do{
				out.add(cclass);
			}while(!(cclass = ClassUtil.toValue(cclass.getSuperclass())).equals(Object.class));
			cclass = ClassUtil.toValue(Object.class);
			out.add(cclass);
		}
		return out;
	}
}
